package com.jboltai.event;

import cn.hutool.core.util.IdUtil;
import com.jboltai.config.JBoltAIConfig;
import com.jboltai.event.chain.ChainNode;
import com.jboltai.event.handler.EventHandler;
import com.jboltai.scheduler.EventBus;
import com.jboltai.util.share.AIEventThreadShareData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

/**
 * 事件
 */
public abstract class Event<T extends Event, ResultType, HandlerType extends EventHandler> implements IEvent<T, ResultType, HandlerType> {

    protected static final Logger LOGGER = LoggerFactory.getLogger(JBoltAIConfig.LOGGER_NAME);



    protected EventType type;

    protected String id;

    protected HandlerType eventHandler;

    /**
     * 事件状态
     */
    protected volatile EventState state = EventState.WAITING;

    /**
     * 所在的事件链节点
     */
    protected ChainNode chainNode;

    /**
     * 失败原因
     */
    protected EventError error;

    /**
     * 成功结果
     */
    protected ResultType result;

    /**
     * 等待执行的超时时间戳，0代表一直在队列中等待执行，>0代表超时时间戳，过了这个时间不再等待
     */
    protected long waitTimestamp;

    /**
     * 事件身上绑定的额外的数据
     */
    protected Map<String, Object> attrs;


    /**
     * 阻塞执行的锁
     */
    protected CountDownLatch waitLatch = new CountDownLatch(1);

    protected StartHandler<T> startHandler;

    protected SuccessHandler<T, ResultType> successHandler;

    protected FailHandler<T> failHandler;

    protected CompleteHandler<T> completeHandler;

    protected CancelHandler<T> cancelHandler;

    protected List<StateChangeHandler<T>> stateChangeHandlers;


    protected AIEventThreadShareData threadShareData;

    /**
     * 是否同步执行
     */
    private boolean isSync = false;

    private boolean prevHandleDone = false;

    /**
     * 是否执行过complete回调，防止重复执行
     */
    private boolean completeDone = false;


    protected Event(EventType type) {
        this.type = type;
        this.id = IdUtil.fastSimpleUUID();
    }


    protected ChainNode getChainNode() {
        return chainNode;
    }

    public void setChainNode(ChainNode chainNode) {
        this.chainNode = chainNode;
    }

    /**
     * 调用大模型之前要做的内部处理，在setState中当state=Processing时触发，只触发一次
     */
    protected void innerPrevHandle() {
        //由具体的子类自己实现
    }

    /**
     * 成功返回数据后的内部处理
     */
    protected void innerSuccessHandle(ResultType result) {
        //由具体的子类自己实现
    }
    /**
     * cancel后的内部处理
     */
    protected void innerCancelHandle() {
        //由具体的子类自己实现
    }

    @Override
    public T onSuccess(SuccessHandler<T, ResultType> successHandler) {
        if (this.successHandler != null) {
            throw new RuntimeException("successHandler已经设置过了，不可重复设置");
        }
        this.successHandler = successHandler;
        return (T) this;
    }



    /**
     * 成功回调
     * @param result
     */
    @Override
    public void success(ResultType result) {
        if (this.state != EventState.PROCESSING) {
            return;
        }
        innerSuccessHandle(result);
//        this.setState(EventState.SUCCESS);
        if (successHandler != null) {
            successHandler.accept((T) this, result);
        }
        if (eventHandler != null) {
            eventHandler.onSuccess((T) this, result);
        }
    }



    @Override
    public T onFail(FailHandler<T> failHandler) {

        if (this.failHandler != null) {
            throw new RuntimeException("failHandler已经设置过了，不可重复设置");
        }
        this.failHandler = failHandler;
        return (T) this;
    }

    /**
     * 失败 回调
     * @param errorType 错误类型
     * @param errorMsg 错误信息
     * @param e 异常
     */
    @Override
    public void fail(EventErrorType errorType, String errorMsg, Throwable e) {

        fail(new EventError(errorType, errorMsg, e));
    }
    @Override
    public void fail(EventErrorType error, String errorMsg) {
        fail(error, errorMsg, null);
    }
    @Override
    public void fail(EventErrorType error, Throwable e) {
        fail(error, error.getMsg(), e);
    }


    @Override
    public void fail(EventErrorType errorType) {
        fail(errorType, errorType.getMsg(), null);
    }

    @Override
    public void fail(EventError error) {
        EventState prevState = this.state;
        if (this.state != EventState.FAIL && this.setState(EventState.FAIL)) {
            this.setError(error);
            if (failHandler != null) {
                failHandler.accept((T) this, getError());
            };
            if (eventHandler != null) {
                eventHandler.onFail((T) this, getError());
            }
            complete();

        }
    }


    @Override
    public T onComplete(CompleteHandler<T> completeHandler) {
        if (this.completeHandler != null) {
            throw new RuntimeException("completeHandler已经设置过了，不可重复设置");
        }
        this.completeHandler = completeHandler;
        return (T) this;
    }



    @Override
    public void cancel() {
        if (this.state != EventState.CANCEL && this.setState(EventState.CANCEL)) {
            innerCancelHandle();
            if (this.cancelHandler != null) {
                this.cancelHandler.accept((T) this);
            }
            if (this.eventHandler != null) {
                this.eventHandler.onCancel((T) this);
            }
            try {
                complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    @Override
    public T onStart(StartHandler<T> startHandler) {
        if (this.startHandler != null) {
            throw new RuntimeException("startHandler已经设置过了，不可重复设置");
        }
        this.startHandler = startHandler;
        return (T) this;
    }


    @Override
    public T onCancel(CancelHandler<T> cancelHandler) {
        if (this.cancelHandler != null) {
            throw new RuntimeException("cancelHandler已经设置过了，不可重复设置");
        }
        this.cancelHandler = cancelHandler;
        return (T) this;
    }


    @Override
    public T onStateChange(StateChangeHandler<T> stateChangeHandler) {
        if (this.stateChangeHandlers == null) {
            this.stateChangeHandlers = new ArrayList<>();
        }
        this.stateChangeHandlers.add(stateChangeHandler);
        return (T) this;
    }


    /**
     * 成功回调
     */
    @Override
    public void complete() {
        try {
            if (completeDone) return;
            if (completeHandler != null) {
                completeHandler.accept((T) this);
            };
            if (eventHandler != null) {
                eventHandler.onComplete((T) this);
            };
            completeDone = true;
        } catch (Exception e ) {
            e.printStackTrace();
            LOGGER.error("事件结束时执行onComplete回调发生异常", e);
            this.state = EventState.FAIL;
            throw new RuntimeException(e);
        } finally {
//            AIEventThreadShareData.clear();
            waitLatch.countDown();
            EventBus.unHold(this.id);

            if (this.chainNode != null) {
                //该事件是某个链上的节点
                switch (this.state) {
                    case FAIL:
                        this.chainNode.fail("节点[" + this.getId() + "]执行失败：" + error!=null?error.getMsg():"", error!=null ? error.getException():null);
                        break;
                    case SUCCESS:
                        this.chainNode.success();
                        break;

                }
            }

        }

    }



    /**
     * 等待事件执行结束
     */
    @Override
    public void await() {
        try {
            isSync = true;
            waitLatch.await();
        } catch (InterruptedException e) {
            LOGGER.error("事件Complete发生异常");
            e.printStackTrace();
        }
    }

    /**
     * 阻塞并等待事件完成，获取结果
     * @return
     */
    public ResultType get() {
        this.dispatch();
        this.await();
        return this.getResult();
    }

    /**
     * 发布该事件，将事件插入队列等待执行
     * @return
     */
    @Override
    public T publish() {
        EventBus.publish(this);
        return (T) this;
    }

    /**
     * 发布该事件，并立即分配资源执行
     * @return
     */
    @Override
    public T dispatch() {
        EventBus.dispatch(this);
        return (T) this;
    }

    /**
     * 在事件上绑定一些数据，方便在各个回调中使用
     * @param key
     * @param value
     * @return
     */
    @Override
    public T setAttr(String key, Object value) {
        if (this.attrs == null) {
            this.attrs = new HashMap<>();
        }
        this.attrs.put(key, value);
        return (T) this;
    }

    /**
     * 在事件上绑定一些数据，方便在各个回调中使用。
     * @param keyValues 必须按照key，value，key，value的格式传入，并且key必须是字符串
     * @return
     */
    @Override
    public T setAttrs(Object... keyValues) {
        if (keyValues == null || keyValues.length == 0) {
            return (T) this;
        }
        if (keyValues.length % 2 != 0) {
            throw new IllegalArgumentException("keyValues必须按照key，value，key，value的格式成对传入");
        }
        for (int i = 0; i < keyValues.length; i+=2) {
            this.setAttr((String) keyValues[i], keyValues[i+1]);
        }
        return (T) this;
    }

    /**
     * 在事件上绑定一些数据，方便在各个回调中使用。
     * @param map
     * @return
     */
    @Override
    public T setAttrs(Map map) {
        if (map == null || map.size() == 0) {
            return (T) this;
        }
        if (this.attrs == null) {
            this.attrs = new HashMap<>();
        }
        this.attrs.putAll(map);
        return (T) this;
    }



    @Override
    public <R> R getAttr(String key) {
        if (this.attrs == null) {
            return null;
        }
        return (R)this.attrs.get(key);
    }


    @Override
    public boolean isSync() {
        return isSync;
    }

    @Override
    public EventType getType() {
        return type;
    }

    /**
     * 指定id
     * @param id
     * @return
     */
    public T setId(String id) {
        this.id = id;
        return (T) this;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public EventState getState() {
        return state;
    }

    @Override
    public EventError getError() {
        return error;
    }

    @Override
    public final boolean setState(EventState state) {
        //重复触发某个状态
        if (this.state == state) return true;
        //状态已经变成了最终状态，不允许再更改
        if (this.state == EventState.CANCEL || this.state == EventState.SUCCESS || this.state == EventState.FAIL) return false;

        synchronized (this) {
            // 防止线程安全问题，再写一遍，上面那一边可以提升性能，不用进锁，就可以结束流程
            if (this.state == state) return false;
            if (this.state == EventState.CANCEL || this.state == EventState.SUCCESS || this.state == EventState.FAIL) return false;

            switch (state) {
                case PROCESSING: {
                    if (prevHandleDone == false) {
                        //处理前执行前置内部处理
                        innerPrevHandle();
                        prevHandleDone = true;
                    }
                    if (this.startHandler != null) {
                        try {
                            this.startHandler.accept((T) this);
                        } catch (Exception e) {
                            this.fail(EventErrorType.ON_START_ERROR, e);
                            return false;
                        }
                    }
                    if (this.eventHandler != null) {
                        try {
                            this.eventHandler.onStart((T) this);
                        } catch (Exception e) {
                            this.fail(EventErrorType.ON_START_ERROR, e);
                            return false;
                        }
                    }

                    break;
                }

            }

            if (this.stateChangeHandlers != null) {
                //状态改变了
                for (StateChangeHandler<T> handler : this.stateChangeHandlers) {
                    handler.accept((T) this, state);
                }
            }
            if (this.eventHandler != null) {
                this.eventHandler.onStateChange((T) this, state);
            }
            this.state = state;

        }


        return true;
    }

    @Override
    public void setError(EventError error) {
        this.error = error;
    }

    @Override
    public ResultType getResult() {
        return result;
    }

    @Override
    public void setResult(ResultType result) {

        this.result = result;
    }


    @Override
    public long getWaitTimestamp() {
        return waitTimestamp;
    }

    /**
     * 设置超时等待时间戳，0代表不限制
     * @param waitTimestamp
     * @return
     */
    @Override
    public T setWaitTimestamp(long waitTimestamp) {
        this.waitTimestamp = waitTimestamp;
        return (T) this;
    }

    @Override
    public boolean isSuccess(){
        return EventState.SUCCESS == this.state;
    }

    @Override
    public boolean isFail(){
        return EventState.FAIL == this.state;
    }

    @Override
    public boolean isProcessing(){
        return EventState.PROCESSING == this.state;
    }

    @Override
    public boolean isWaiting(){
        return EventState.WAITING == this.state;
    }


    public AIEventThreadShareData getThreadShareData() {
        return threadShareData;
    }

    public T setThreadShareData(AIEventThreadShareData threadShareData) {
        this.threadShareData = threadShareData;
        return (T) this;
    }

    public T setThreadShareData(Map<String,Object> data) {
        return setThreadShareData(new AIEventThreadShareData(data));
    }

    public HandlerType getHandler() {
        return eventHandler;
    }

    public T setHandler(HandlerType eventHandler) {
        this.eventHandler = eventHandler;
        return (T) this;
    }
}
